/***************************************************************************

Copyright (c) Microsoft Corporation. All rights reserved.
This code is licensed under the Visual Studio SDK license terms.
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

***************************************************************************/

using System;
using System.Collections;
using System.Text;
using System.Reflection;
using System.ComponentModel.Design;
using Microsoft.VsSDK.UnitTestLibrary;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.Shell;
using MagnusGrindalBakken.TextTools;

namespace TextTools_UnitTests.MenuItemTests
{
    [TestClass]
    public class MenuItemTest
    {
        [TestMethod]
        public void InitializeDeleteCurrentWordMenuCommand()
        {
            this.BaseInitializeMenuCommandTest((int)MagnusGrindalBakken.TextTools.PkgCmdIDList.cmdDeleteCurrentWord);
        }

        [TestMethod]
        public void InitializeDeleteWordBackwardsMenuCommand()
        {
            this.BaseInitializeMenuCommandTest((int)MagnusGrindalBakken.TextTools.PkgCmdIDList.cmdDeleteBackwardsToPreviousUppercase);
        }

        [TestMethod]
        public void InitializeDeleteWordForwardsMenuCommand()
        {
            this.BaseInitializeMenuCommandTest((int)MagnusGrindalBakken.TextTools.PkgCmdIDList.cmdDeleteForwardsToNextUppercase);
        }

        private void BaseInitializeMenuCommandTest(int commandId)
        {
            // Create the package
            IVsPackage package = new TextToolsPackage() as IVsPackage;

            // Create a basic service provider
            OleServiceProvider serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();

            // Site the package
            Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");

            // Verify that the menu command can be found
            CommandID menuCommandID = new CommandID(MagnusGrindalBakken.TextTools.GuidList.guidTextToolsCmdSet, commandId);
            System.Reflection.MethodInfo info = typeof(Package).GetMethod("GetService", BindingFlags.Instance | BindingFlags.NonPublic);
            Assert.IsNotNull(info);
            OleMenuCommandService mcs = info.Invoke(package, new object[] { (typeof(IMenuCommandService)) }) as OleMenuCommandService;
            Assert.IsNotNull(mcs.FindCommand(menuCommandID));
        }

        [TestMethod]
        public void DeleteCurrentWordCallbackTest()
        {
            this.BaseCallbackTest("DeleteCurrentWordCallback");
        }

        [TestMethod]
        public void DeleteWordBackwardsCallbackTest()
        {
            this.BaseCallbackTest("DeleteWordBackwardsCallback");
        }

        [TestMethod]
        public void DeleteWordForwardsCallbackTest()
        {
            this.BaseCallbackTest("DeleteWordForwardsCallback");
        }

        private void BaseCallbackTest(string commandName)
        {
            // Create the package
            IVsPackage package = new TextToolsPackage() as IVsPackage;
            Assert.IsNotNull(package, "The object does not implement IVsPackage");

            // Create a basic service provider
            OleServiceProvider serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();

            // Create a UIShell service mock and proffer the service so that it can called from the MenuItemCallback method
            BaseMock uishellMock = UIShellServiceMock.GetUiShellInstance();
            serviceProvider.AddService(typeof(SVsUIShell), uishellMock, true);

            // Site the package
            Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");

            //Invoke private method on package class and observe that the method does not throw
            System.Reflection.MethodInfo info = package.GetType().GetMethod(commandName, BindingFlags.Instance | BindingFlags.NonPublic);
            Assert.IsNotNull(info, string.Format("Failed to get the private method {0} through reflection", commandName));
            info.Invoke(package, new object[] { null, null });

            //Clean up services
            serviceProvider.RemoveService(typeof(SVsUIShell));
        }
    }
}
